package com.xlzcx.xltz.utils;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 作者: 李咨辰
 * 文件名: mail.java
 * 路径: com.lzc.mail
 * 时间: 2024-08-28 14:46
 * 版本: 1.0
 * 描述: TODO 邮件
 **/
public class EmailUtil {
    private String userName;
    //账号密码
    private String password;
    //邮箱服务器地址
    private String host;
    //邮箱服务器端口
    private String port;
    private final Session session;

    public EmailUtil(String userName, String password, String host, String port) {
        this.userName = userName;
        this.password = password;
        this.host = host;
        this.port = port;
        Properties properties = new Properties();
        //设置服务器
        properties.put("mail.smtp.host", host);
        //服务器端口
        properties.put("mail.smtp.port", port);
        //开启SSL验证
        properties.put("mail.smtp.auth", true);
        properties.put("mail.smtp.ssl.enable", "true");
        properties.put("mail.smtp.ssl.protocols", "TLSv1.2");
        //创建连接
        this.session = Session.getInstance(properties, new Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                //连接账号
                return new javax.mail.PasswordAuthentication(userName, password);
            }
        });
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getPort() {
        return port;
    }

    public void setPort(String port) {
        this.port = port;
    }

    /**
     * 单发会话信息
     *
     * @param to      接收方邮箱
     * @param subject 主题
     * @return Message对象
     */
    private Message getMessage(String name, String to, String subject, String type) {
        // 创建一个基于当前会话的 MimeMessage 对象，代表一封邮件
        Message message = new MimeMessage(this.session);
        try {
            // 设置发件人邮箱地址和发件人名称
            InternetAddress form = new InternetAddress(userName, name);
            message.setFrom(form);
            // 设置收件人地址，Message.RecipientType.TO 表示收件人类型为 TO（直接收件人）
            Message.RecipientType recipientType;
            if (type == null) {
                recipientType = Message.RecipientType.TO;
            } else {
                switch (type) {
                    case "cc":
                    case "CC":
                        recipientType = Message.RecipientType.CC;
                        break;
                    case "bcc":
                    case "BCC":
                        recipientType = Message.RecipientType.BCC;
                        break;
                    default:
                        recipientType = Message.RecipientType.TO;
                        break;
                }
            }
            if (to.contains(",")) {
                //群发
                message.addRecipients(recipientType, InternetAddress.parse(to));
            } else {
                //单发
                message.setRecipient(recipientType, new InternetAddress(to));//单发
            }
            //设置邮件主题
            message.setSubject(subject);
        } catch (UnsupportedEncodingException | MessagingException e) {
            throw new RuntimeException(e);
        }
        return message;
    }

    /**
     * 发送邮件
     *
     * @param name      发件人昵称
     * @param to        收件人邮箱
     * @param subject   邮件主题
     * @param body      邮件内容
     * @param html      html判断
     * @param picture   图片
     * @param documents 附件
     * @param type      邮件类型
     * @return true
     */
    public boolean sendAMessage(String name, String to, String subject, String body, boolean html, HashMap<String, String> picture, String[] documents, String type) {
        // 创建一个基于当前会话的 MimeMessage 对象，代表一封邮件
        Message message = getMessage(name, to, subject, type);
        try {
            Multipart multipart = new MimeMultipart();
            if (html) {//html类型
                BodyPart htmlPart = new MimeBodyPart();
                htmlPart.setContent(body, "text/html;charset=utf-8");
                multipart.addBodyPart(htmlPart);
                //插图片
                if (picture != null) {
                    for (Map.Entry<String, String> entry : picture.entrySet()) {
                        String key = entry.getKey();
                        String value = entry.getValue();
                        //插入img图片
                        MimeBodyPart imagePart = new MimeBodyPart();
                        //图片路径
                        FileDataSource fds = new FileDataSource(value);
                        //插入
                        imagePart.setDataHandler(new DataHandler(fds));
                        //插入到指定位置
                        imagePart.setHeader("Content-ID", "<" + key + ">");

                        //将图片存入邮件中
                        multipart.addBodyPart(imagePart);
                    }
                }
            } else {//文本类型
                MimeBodyPart textPart = new MimeBodyPart();
                textPart.setText(body);
                multipart.addBodyPart(textPart);
            }
            //附件
            if (documents != null) {
                for (int i = 0; i < documents.length; i++) {
                    BodyPart attachmentsPart = new MimeBodyPart();
                    attachmentsPart.setDataHandler(new DataHandler(new FileDataSource(documents[i])));
                    String fileName;
                    if (documents[i].contains("\\")) {
                        fileName = "附件" + (i + 1) + "-" + (documents[i].replaceFirst(".*\\\\", ""));
                    } else if (documents[i].contains("/")) {
                        fileName = "附件" + (i + 1) + "-" + (documents[i].replaceFirst(".*/", ""));
                    } else {
                        fileName = "附件" + (i + 1) + "-" + documents[i];
                    }
                    attachmentsPart.setFileName(MimeUtility.encodeText(fileName, "UTF-8", "B")); // 设置图片附件的文件名
                    multipart.addBodyPart(attachmentsPart);
                }
            }
            message.setContent(multipart);
            //发送邮件
            Transport.send(message);
            return true;
        } catch (MessagingException | UnsupportedEncodingException e) {
            //throw new RuntimeException(e);
            return false;
        }
    }

    /**
     * 数组类型邮件列表转字符串类型
     *
     * @param to 数组类型字符串列表
     * @return 字符串类型列表
     */
    private static String toSB(String[] to) {
        StringBuilder sb = new StringBuilder();
        for (String toFor : to) {
            sb.append(toFor).append(",");
        }
        return sb.toString();
    }


    /**
     * 基础数据
     *
     * @param name    发件人昵称
     * @param to      收件人邮箱
     * @param subject 邮件主题
     * @param body    邮件内容
     * @return 成功返回true;
     */
    public boolean sendAMessage(String name, String to, String subject, String body) {
        return sendAMessage(name, to, subject, body, false, null, null, null);
    }

    /**
     * 基础数据
     *
     * @param name    发件人昵称
     * @param tos     收件人邮箱数组
     * @param subject 邮件主题
     * @param body    邮件内容
     * @return 成功返回true;
     */
    public boolean sendAMessage(String name, String[] tos, String subject, String body) {
        return sendAMessage(name, toSB(tos), subject, body, false, null, null, null);
    }

    /**
     * html判读
     *
     * @param name    发件人昵称
     * @param to      收件人邮箱数组
     * @param subject 邮件主题
     * @param body    邮件内容
     * @param html    html判断
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String to, String subject, String body, boolean html) {
        return sendAMessage(name, to, subject, body, html, null, null, null);
    }

    /**
     * html判读
     *
     * @param name    发件人昵称
     * @param tos     收件人邮箱数组
     * @param subject 邮件主题
     * @param body    邮件内容
     * @param html    html判断
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String[] tos, String subject, String body, boolean html) {
        return sendAMessage(name, toSB(tos), subject, body, html, null, null, null);
    }

    /**
     * 图片插入
     *
     * @param name    发件人昵称
     * @param to      收件人邮箱
     * @param subject 邮件主题
     * @param body    邮件内容
     * @param picture 图片列表
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String to, String subject, String body, HashMap<String, String> picture) {
        return sendAMessage(name, to, subject, body, false, picture, null, null);
    }

    /**
     * 图片插入
     *
     * @param name    发件人昵称
     * @param tos     收件人邮箱数组
     * @param subject 邮件主题
     * @param body    邮件内容
     * @param picture 图片列表
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String[] tos, String subject, String body, HashMap<String, String> picture) {
        return sendAMessage(name, toSB(tos), subject, body, false, picture, null, null);
    }

    /**
     * 附件
     *
     * @param name      发件人昵称
     * @param to        收件人昵称
     * @param subject   邮件主题
     * @param body      邮件内容
     * @param documents 附件
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String to, String subject, String body, String[] documents) {
        return sendAMessage(name, to, subject, body, false, null, documents, null);
    }

    /**
     * 附件
     *
     * @param name      发件人昵称
     * @param tos       收件人邮箱数组
     * @param subject   邮件主题
     * @param body      邮件内容
     * @param documents 附件
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String[] tos, String subject, String body, String[] documents) {
        return sendAMessage(name, toSB(tos), subject, body, false, null, documents, null);
    }

    /**
     * 邮件类型
     *
     * @param name    发件人昵称
     * @param to      收件人邮箱
     * @param subject 邮件主题
     * @param body    邮件内容
     * @param type    邮件类型
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String to, String subject, String body, String type) {
        return sendAMessage(name, to, subject, body, false, null, null, type);
    }

    /**
     * 邮件类型
     *
     * @param name    发件人昵称
     * @param tos     收件人邮箱数组
     * @param subject 邮件主题
     * @param body    邮件内容
     * @param type    邮件类型
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String[] tos, String subject, String body, String type) {
        return sendAMessage(name, toSB(tos), subject, body, false, null, null, type);
    }

    /**
     * html判断 , 图片列表
     *
     * @param name    发件人昵称
     * @param to      收件人邮箱
     * @param subject 邮件主题
     * @param body    邮件内容
     * @param html    html判断
     * @param picture 图片列表
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String to, String subject, String body, boolean html, HashMap<String, String> picture) {
        return sendAMessage(name, to, subject, body, html, picture, null, null);
    }

    /**
     * html判断 , 图片列表
     *
     * @param name    发件人昵称
     * @param tos     收件人邮箱数组
     * @param subject 邮件主题
     * @param body    邮件内容
     * @param html    html判断
     * @param picture 图片列表
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String[] tos, String subject, String body, boolean html, HashMap<String, String> picture) {
        return sendAMessage(name, toSB(tos), subject, body, html, picture, null, null);
    }

    /**
     * html判断 , 附件数组
     *
     * @param name      发件人昵称
     * @param to        收件人邮箱
     * @param subject   邮件主题
     * @param body      邮件内容
     * @param html      html判断
     * @param documents 附件数组
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String to, String subject, String body, boolean html, String[] documents) {
        return sendAMessage(name, to, subject, body, html, null, documents, null);
    }

    /**
     * html判断 , 附件数组
     *
     * @param name      发件人昵称
     * @param tos       收件人邮箱数组
     * @param subject   邮件主题
     * @param body      邮件内容
     * @param html      html判断
     * @param documents 附件数组
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String[] tos, String subject, String body, boolean html, String[] documents) {
        return sendAMessage(name, toSB(tos), subject, body, html, null, documents, null);
    }

    /**
     * html判断 , 邮件类型
     *
     * @param name    发件人昵称
     * @param to      收件人邮箱
     * @param subject 邮件主题
     * @param body    邮件内容
     * @param html    html判断
     * @param type    邮件类型
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String to, String subject, String body, boolean html, String type) {
        return sendAMessage(name, to, subject, body, html, null, null, type);
    }

    /**
     * html判断 , 邮件类型
     *
     * @param name    发件人昵称
     * @param tos     收件人邮箱数组
     * @param subject 邮件主题
     * @param body    邮件内容
     * @param html    html判断
     * @param type    邮件类型
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String[] tos, String subject, String body, boolean html, String type) {
        return sendAMessage(name, toSB(tos), subject, body, html, null, null, type);
    }

    /**
     * 图片列表 , 附件数组
     *
     * @param name      发件人昵称
     * @param to        收件人邮箱
     * @param subject   邮件主题
     * @param body      邮件内容
     * @param picture   图片列表
     * @param documents 附件数组
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String to, String subject, String body, HashMap<String, String> picture, String[] documents) {
        return sendAMessage(name, to, subject, body, false, picture, documents, null);
    }

    /**
     * 图片列表 , 附件数组
     *
     * @param name      发件人昵称
     * @param tos       收件人邮箱数组
     * @param subject   邮件主题
     * @param body      邮件内容
     * @param picture   图片列表
     * @param documents 附件数组
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String[] tos, String subject, String body, HashMap<String, String> picture, String[] documents) {
        return sendAMessage(name, toSB(tos), subject, body, false, picture, documents, null);
    }

    /**
     * 图片列表 , 邮件类型
     *
     * @param name    发件人昵称
     * @param to      收件人邮箱
     * @param subject 邮件主题
     * @param body    邮件内容
     * @param picture 图片列表
     * @param type    邮件类型
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String to, String subject, String body, HashMap<String, String> picture, String type) {
        return sendAMessage(name, to, subject, body, false, picture, null, type);
    }

    /**
     * 图片列表 , 邮件类型
     *
     * @param name    发件人昵称
     * @param tos     收件人邮箱数组
     * @param subject 邮件主题
     * @param body    邮件内容
     * @param picture 图片列表
     * @param type    邮件类型
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String[] tos, String subject, String body, HashMap<String, String> picture, String type) {
        return sendAMessage(name, toSB(tos), subject, body, false, picture, null, type);
    }

    /**
     * 附件数组 , 邮件类型
     *
     * @param name      发件人昵称
     * @param to        收件人邮箱
     * @param subject   邮件主题
     * @param body      邮件内容
     * @param documents 附件数组
     * @param type      邮件类型
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String to, String subject, String body, String[] documents, String type) {
        return sendAMessage(name, to, subject, body, false, null, documents, type);
    }

    /**
     * 附件数组 , 邮件类型
     *
     * @param name      发件人昵称
     * @param tos       收件人邮箱数组
     * @param subject   邮件主题
     * @param body      邮件内容
     * @param documents 附件数组
     * @param type      邮件类型
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String[] tos, String subject, String body, String[] documents, String type) {
        return sendAMessage(name, toSB(tos), subject, body, false, null, documents, type);
    }

    /**
     * html判断 , 图片列表 , 附件数组
     *
     * @param name      发件人昵称
     * @param to        收件人邮箱
     * @param subject   邮件主题
     * @param body      邮件内容
     * @param html      html判断
     * @param picture   图片列表
     * @param documents 附件数组
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String to, String subject, String body, boolean html, HashMap<String, String> picture, String[] documents) {
        return sendAMessage(name, to, subject, body, html, picture, documents, null);
    }

    /**
     * html判断 , 图片列表 , 附件数组
     *
     * @param name      发件人昵称
     * @param tos       收件人邮箱数组
     * @param subject   邮件主题
     * @param body      邮件内容
     * @param html      html判断
     * @param picture   图片列表
     * @param documents 附件数组
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String[] tos, String subject, String body, boolean html, HashMap<String, String> picture, String[] documents) {
        return sendAMessage(name, toSB(tos), subject, body, html, picture, documents, null);
    }

    /**
     * html判断 , 图片列表 , 附件数组 , 邮件类型
     *
     * @param name    发件人昵称
     * @param to      收件人邮箱
     * @param subject 邮件主题
     * @param body    邮件内容
     * @param html    html判断
     * @param picture 图片列表
     * @param type    邮件类型
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String to, String subject, String body, boolean html, HashMap<String, String> picture, String type) {
        return sendAMessage(name, to, subject, body, html, picture, null, type);
    }

    /**
     * html判断 , 图片列表 , 附件数组 , 邮件类型
     *
     * @param name    发件人昵称
     * @param tos     收件人邮箱数组
     * @param subject 邮件主题
     * @param body    邮件内容
     * @param html    html判断
     * @param picture 图片列表
     * @param type    邮件类型
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String[] tos, String subject, String body, boolean html, HashMap<String, String> picture, String type) {
        return sendAMessage(name, toSB(tos), subject, body, html, picture, null, type);
    }

    /**
     * html判断 , 图片列表 , 附件数组 , 邮件类型
     *
     * @param name      发件人昵称
     * @param to        收件人邮箱
     * @param subject   邮件主题
     * @param body      邮件内容
     * @param html      html判断
     * @param documents 附件数组
     * @param type      邮件类型
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String to, String subject, String body, boolean html, String[] documents, String type) {
        return sendAMessage(name, to, subject, body, html, null, documents, type);
    }

    /**
     * html判断 , 图片列表 , 附件数组 , 邮件类型
     *
     * @param name      发件人昵称
     * @param tos       收件人邮箱数组
     * @param subject   邮件主题
     * @param body      邮件内容
     * @param html      html判断
     * @param documents 附件数组
     * @param type      邮件类型
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String[] tos, String subject, String body, boolean html, String[] documents, String type) {
        return sendAMessage(name, toSB(tos), subject, body, html, null, documents, type);
    }

    /**
     * html判断 , 图片列表 , 附件数组 , 邮件类型
     *
     * @param name      发件人昵称
     * @param to        收件人邮箱
     * @param subject   邮件主题
     * @param body      邮件内容
     * @param picture   图片列表
     * @param documents 附件数组
     * @param type      邮件类型
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String to, String subject, String body, HashMap<String, String> picture, String[] documents, String type) {
        return sendAMessage(name, to, subject, body, false, picture, documents, type);
    }

    /**
     * html判断 , 图片列表 , 附件数组 , 邮件类型
     *
     * @param name      发件人昵称
     * @param tos       收件人邮箱数组
     * @param subject   邮件主题
     * @param body      邮件内容
     * @param picture   图片列表
     * @param documents 附件数组
     * @param type      邮件类型
     * @return 成功返回true
     */
    public boolean sendAMessage(String name, String[] tos, String subject, String body, HashMap<String, String> picture, String[] documents, String type) {
        return sendAMessage(name, toSB(tos), subject, body, false, picture, documents, type);
    }
}